package com.haohan.jingyuan.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.haohan.jingyuan.config.properties.OssProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 阿里云OSS工具类
 * 提供文件上传、URL获取等功能
 *
 * @author haohan
 * @since 2025-01-27
 */
@Slf4j
@Component
public class OssUtil {

    /**
     * OSS配置属性
     */
    @Autowired
    private OssProperties ossProperties;

    /**
     * 上传文件到OSS
     *
     * @param file 上传的文件
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        OSS ossClient = null;
        try {
            // 创建OSS客户端
            ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                    ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());

            // 生成文件名
            String fileName = generateFileName(file.getOriginalFilename());
            String objectName = ossProperties.getPathPrefix() + fileName;

            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(ossProperties.getBucketName(), objectName, file.getInputStream());

            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());
            putObjectRequest.setMetadata(metadata);

            // 执行上传
            ossClient.putObject(putObjectRequest);

            return objectName.replace(ossProperties.getPathPrefix(), "");

        } catch (IOException e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 上传文件流到OSS
     *
     * @param inputStream 文件输入流
     * @param fileName    文件名
     * @param contentType 文件类型
     * @return 文件访问URL
     */
    public String uploadFile(InputStream inputStream, String fileName, String contentType) {
        if (inputStream == null) {
            throw new IllegalArgumentException("文件流不能为空");
        }

        OSS ossClient = null;
        try {
            // 创建OSS客户端
            ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                    ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());

            // 生成文件名
            String generatedFileName = generateFileName(fileName);
            String objectName = ossProperties.getPathPrefix() + generatedFileName;

            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(ossProperties.getBucketName(), objectName, inputStream);

            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(contentType);
            putObjectRequest.setMetadata(metadata);

            // 执行上传
            ossClient.putObject(putObjectRequest);

            // 返回ossKey（去掉pathPrefix）
            return objectName.replace(ossProperties.getPathPrefix(), "");

        } catch (Exception e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 获取文件访问URL
     *
     * @param objectName 对象名称（文件在OSS中的路径）
     * @return 文件访问URL
     */
    public String getFileUrl(String objectName) {
        objectName = ossProperties.getPathPrefix() + objectName;
        return generatePresignedUrl(objectName, ossProperties.getUrlExpireSeconds());
        // return "https://" + ossProperties.getBucketName() + "." +
        //         ossProperties.getEndpoint().replace("https://", "") + "/" + objectName;
    }

    /**
     * 生成预签名URL
     *
     * @param objectName    对象名称（文件在OSS中的路径）
     * @param expireSeconds 过期时间（秒）
     * @return 可访问的预签名URL
     */
    public String generatePresignedUrl(String objectName, Long expireSeconds) {
        OSS ossClient = null;
        try {
            long seconds = (expireSeconds == null || expireSeconds <= 0) ? 3600L : expireSeconds;
            Date expiration = new Date(System.currentTimeMillis() + seconds * 1000);
            ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                    ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());
            URL url = ossClient.generatePresignedUrl(ossProperties.getBucketName(), objectName, expiration);
            return url.toString();
        } catch (Exception e) {
            log.error("生成预签名URL失败", e);
            throw new RuntimeException("生成预签名URL失败: " + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 删除OSS中的文件
     *
     * @param objectName 对象名称（文件在OSS中的路径）
     * @return 是否删除成功
     */
    public boolean deleteFile(String objectName) {
        OSS ossClient = null;
        try {
            // 创建OSS客户端
            ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                    ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());

            // 删除文件
            ossClient.deleteObject(ossProperties.getBucketName(), objectName);
            return true;

        } catch (Exception e) {
            log.error("文件删除失败", e);
            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 检查文件是否存在
     *
     * @param objectName 对象名称（文件在OSS中的路径）
     * @return 文件是否存在
     */
    public boolean doesFileExist(String objectName) {
        OSS ossClient = null;
        try {
            // 创建OSS客户端
            ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                    ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());

            // 检查文件是否存在
            return ossClient.doesObjectExist(ossProperties.getBucketName(), objectName);

        } catch (Exception e) {
            log.error("检查文件是否存在失败", e);
            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 生成唯一文件名
     *
     * @param originalFileName 原始文件名
     * @return 生成的文件名
     */
    private String generateFileName(String originalFileName) {
        // 获取文件扩展名
        String extension = "";
        if (originalFileName != null && originalFileName.contains(".")) {
            extension = originalFileName.substring(originalFileName.lastIndexOf("."));
        }

        // 生成日期路径
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        String datePath = dateFormat.format(new Date());

        // 生成唯一文件名
        String uuid = UUID.randomUUID().toString().replace("-", "");

        return datePath + "/" + uuid + extension;
    }
}
